package com.example.demo.utils;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.poi.excel.style.StyleUtil;
import com.example.demo.model.ExcelModel;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import sun.plugin2.util.ColorUtil;

import java.io.OutputStream;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
 * Created by ruwenbo on 2017/12/17.
 */
public class ExcelUtil {

    private ExcelUtil() {

    }

    /**
     * @MethodName  : listToExcel
     * @Description : 导出Excel（可以导出到本地文件系统，也可以导出到浏览器，可自定义工作表大小）
     * @param list      数据源
     * @param fieldList      类的英文属性和Excel中的中文列名的对应关系
     * 如果需要的是引用对象的属性，则英文属性使用类似于EL表达式的格式
     * 如：list中存放的都是student，student中又有college属性，而我们需要学院名称，则可以这样写
     * fieldMap.put("college.collegeName","学院名称")
     * @param sheetName 工作表的名称
     * @param sheetSize 每个工作表中记录的最大个数
     * @param out       导出流
     * @throws Exception
     */
    public static <T>  void   listToExcel (List<T> list , List<ExcelModel> fieldList, String sheetName, int sheetSize, OutputStream out) throws Exception {

        if (null == list || list.size() == 0) {
            throw new Exception("数据源中没有数据");
        }

        if (sheetSize > 65535 || sheetSize < 1) {
            sheetSize = 65535;
        }

        // 创建工作潽并发送到outputstream指定的位置
        HSSFWorkbook workbook;
        try {

            workbook = new HSSFWorkbook();
            //因为2003的Excel一个工作表最多可以有65536条记录，除去列头剩下65535条
            //所以如果记录太多，需要放到多个工作表中，其实就是个分页的过程
            //1.计算一共有多少个工作表
            double sheetNum = Math.ceil(list.size() / new Integer(sheetSize).doubleValue());

            // 2.创建相应的工作噗,并向其中添加数据
            for (int i = 0; i < sheetNum; i++) {
                // 如果只有一个工作噗
                HSSFSheet sheet = workbook.createSheet();

                workbook.setSheetName(i, sheetName+i);
                if (1 == sheetNum) {
                    fillSheet(sheet, list, fieldList, 0, list.size());
                }
                // 如果有多个工作噗
                else {
                    // 获取开始与结束索引
                    int firstIndex=i*sheetSize;
                    int lastIndex= Math.min((i + 1) * sheetSize, list.size());
                    fillSheet(sheet, list, fieldList, firstIndex, lastIndex);
                }
            }
            workbook.write(out);
        } catch (Exception e) {
            e.printStackTrace();
            //如果是ExcelException，则直接抛出
            throw (Exception) e;
            //否则将其它异常包装成ExcelException再抛出
        }
    }

    /**
     * @MethodName  : fillSheet
     * @Description : 向工作表中填充数据
     * @param sheet     工作表
     * @param list  数据源
     * @param fieldList 中英文字段对应关系的List,表头
     * @param firstIndex    开始索引
     * @param lastIndex 结束索引
     */
    private static <T> void fillSheet(HSSFSheet sheet, List<T> list,
                                      List<ExcelModel> fieldList, int firstIndex, int lastIndex) throws NoSuchFieldException, IllegalAccessException {
        HSSFWorkbook workbook = sheet.getWorkbook();
        //定义存放英文字段名和中文字段名的数组        // 填充数组
        String[] enFields = fieldList.stream().map(ExcelModel::getEnField).toArray(String[]::new);
        String[] cnFields = fieldList.stream().map(ExcelModel::getCnField).toArray(String[]::new);
        // 填充表头
        HSSFRow row = sheet.createRow(0);
        for (int i = 0; i < cnFields.length; i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellValue(cnFields[i]);
        }
        // 填充内容
        for (int index = firstIndex; index < lastIndex; index++) {
            int rowNum = index - firstIndex+1;
            T item = list.get(index);
            HSSFRow previousRow = sheet.getRow(rowNum-1);
            row = sheet.createRow(rowNum);
            for (int j = 0; j < cnFields.length; j++) {
                HSSFCellStyle hssfCellStyle = workbook.createCellStyle();
                ExcelModel excelModel = fieldList.get(j);
                Field field = item.getClass().getDeclaredField(enFields[j]);
                field.setAccessible(true);
                Object obj = field.get(item);
                String value = obj == null ? "" : obj.toString();
                HSSFCell cell = row.createCell(j);
//                单元格居中
                if (excelModel.isCenter()){
                    hssfCellStyle.setAlignment(HorizontalAlignment.CENTER);
                    Font font = workbook.createFont();
                    font.setFontHeightInPoints((short) 14);
                    font.setFontName("华文琥珀");
                    font.setColor(HSSFColor.HSSFColorPredefined.RED.getIndex());

                    //6.2创建单元格格式CellStyle
                    HSSFWorkbook hwb = new HSSFWorkbook();
                    HSSFPalette palette = hwb.getCustomPalette();
// get the color which most closely matches the color you want to use
                    HSSFColor myColor = palette.findSimilarColor(64,165,65);
// get the palette index of that color
                    short palIndex = myColor.getIndex();
// code to get the style for the cell goes here
                    font.setColor(palIndex);

                    hssfCellStyle.setFont(font);


                }
//                合并单元格
                if (excelModel.isMerged()){
                    if (previousRow.getCell(j) != null && ObjectUtil.equal(previousRow.getCell(j).getStringCellValue(), value)){
                        sheet.addMergedRegionUnsafe(new CellRangeAddress(rowNum-1, rowNum, j, j));
                    }
                    StyleUtil.setAlign(hssfCellStyle, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
                }
                if (obj instanceof LocalDateTime){
                    value = DateUtil.format((LocalDateTime) obj, excelModel.getFormat());
                }
                cell.setCellStyle(hssfCellStyle);
                cell.setCellValue(value);
//                HSSFRichTextString richString = new HSSFRichTextString(value); //textValue是要设置大小的单元格数据
//                HSSFFont font = workbook.createFont();
//                font.setColor(HSSFColor.HSSFColorPredefined.RED.getIndex());//设置excel数据字体颜色
//                richString.applyFont(font);
//                cell.setCellValue(richString);

            }
        }
    }
}
